-
Notifications
You must be signed in to change notification settings - Fork 1.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement SVCB #1067
Implement SVCB #1067
Conversation
Codecov Report
@@ Coverage Diff @@
## master #1067 +/- ##
=======================================
Coverage 56.09% 56.09%
=======================================
Files 42 42
Lines 10612 10612
=======================================
Hits 5953 5953
Misses 3609 3609
Partials 1050 1050 Continue to review full report at Codecov.
|
[ Quoting <[email protected]> in "Re: [miekg/dns] Implement SVCB (#10..." ]
They're of the form `a=b` or `a="b"`. Because the values of key=value pairs consist of
> basic-visible [which] is VCHAR minus DQUOTE, ";", and "\"
So I should add code to remove the double quotes if they exist.
dunno, if the draft is unclear on that it should be more clear. Or send an email to dnsops
to ask for clarification.
|
[ Quoting <[email protected]> in "Re: [miekg/dns] Implement SVCB (#10..." ]
Which means the wire format of values of key=value pairs depend on keys, and key- value-wireformat-type table was not written which means no one can implement wire format encoding/decoding before the spec is ready.
Missed this previously: https://tools.ietf.org/html/draft-ietf-dnsop-svcb-httpssvc-01#appendix-C.3
C.3. Wire Format
Advice from experts in DNS wire format best practices would be
greatly appreciated to refine the proposed details, overall.
currently the format is:
When SvcFieldValue is non-empty (ServiceForm), it contains a list of
SvcParamKey=SvcParamValue pairs with length-prefixes for the
SvcParamValues, each of which contains:
o a 2 octet field containing the SvcParamKey as an integer in
network byte order.
o a 2 octet field containing the length of the SvcParamValue as an
integer between 0 and 65535 in network byte order (but constrained
by the RDATA and DNS message sizes).
o an octet string of the length defined by the previous field.
this is def *not* how the TXT record does it and a bit bonkers if you ask me.
|
Thank you, that helps, I'll add that. |
[ Quoting <[email protected]> in "Re: [miekg/dns] Implement SVCB (#10..." ]
Thank you, that helps, I'll add that.
also see #1064 (comment)
|
Hello again, I'm adding |
I think we should help shape the wire format for this record using the
experience we gather from trying to implement it. IOW engage on the dnsop
ML to propose a new format
…On Tue, 31 Dec 2019, 17:49 DesWurstes, ***@***.***> wrote:
Hello again, I'm adding key=value wire encoding/decoding. In #1064
<#1064> you suggested those key=value
pairs should be []string in the struct. I believe []byte (or even a
separated [][]byte) in the wireformat would suit better, because it'd allow
the library to be used as a proxy with reserved and private key types
(otherwise we can't deserialize the value, which is of an unknown format).
In addition, packing and unpacking would be more expensive, which I think
is used more often than string serialization/deserialization. Do you agree,
should the struct keep Values as binary?
—
You are receiving this because your review was requested.
Reply to this email directly, view it on GitHub
<#1067?email_source=notifications&email_token=AACWIW57W2YCSFZNIVESIILQ3NZ3LA5CNFSM4KBJ2Z2KYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEH4NZRY#issuecomment-569957575>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AACWIW7GCKMWPAUOWLTWEHTQ3NZ3LANCNFSM4KBJ2Z2A>
.
|
Hello @DesWurstes, are you still working on this by any chance? I'm interested in helping out (if any help is needed) to get this in shape (if you are not interested in working on this anymore I'm also available to take over the work and get it ready, if that's ok with you). We (Cloudflare) are looking into shipping support for HTTSSVC, so this would help greatly.
I don't understand this part. Why does it need to be "private"? If people try to query SVCB or HTTPSSVC records on Cloudflare's DNS servers they will get back nothing, as we don't currently serve these records. In that case a client wouldn't use an ESNI version that Cloudflare servers don't support, and it could either fallback to an older version if it supports it, or not do ESNI at all. |
Hello, My implementation was incomplete because I wasn't sure if the specification would undergo major changes. It seems it has matured. Now I'll rebase it and start working on it again. I'll change
to
so that it doesn't decode when not needed. (and define the type) I wanted to make it private as the draft is not finalized so no server supports it, and those implementing SNI encryption could try to use the SVCB record instead of |
@miekg should I make |
[ Quoting <[email protected]> in "Re: [miekg/dns] Implement SVCB (#10..." ]
@miekg should I make Value field closer to the wireformat than the presentation
format? (Because other ones seem to be keeping data in base64 strings instead
of byte arrays but SvcValueField can be containing a key whose value type we
don't know because it's reserved, so we don't need to process SvcValueField
unless it's required?)
I haven't been following the latest with regards to SVCB, but the structure in go dns
should contain a field that is usable. I.e. the `A` records we use `net.IP`, not `[]byte`
/Miek
…--
Miek Gieben
|
where
etc, because the presentation format usually is helpful, but if they need it in go data types, they can call functions similar to this. (Or functions taking Or to solve the problem similar to |
[ Quoting <[email protected]> in "Re: [miekg/dns] Implement SVCB (#10..." ]
type SvcKeyValue struct {
SvcParamKey uint16
SvcParamValue string
}
where SvcParamValue is the presentation format representation is fine? Then for
defined keys we can add
func (rr *SVCB) getIpv4Hint() (ip net.IP, has bool) {
...
}
Why is such a helper needed? The SvcParamKeys prolly will need a whole slew of constants
defined as well...
|
The array of SvcKeyValues would is in increasing order, they can for-loop until
|
[ Quoting <[email protected]> in "Re: [miekg/dns] Implement SVCB (#10..." ]
https://github.com/miekg/dns/pull/1067/files#
diff-e871404fd69cab40521d6b2178847cf7R184-R219
The array of SvcKeyValues would be ordered, they can for-loop until SvcParamKey
== SVC_PORT for example. Do you prefer:
type SVCB struct {
Hdr RR_Header
Priority uint16
Target string `dns:"domain-name"`
esni ESNI `dns:"-"`
Ipv4hint Ipv4 `dns:"-"`
Alpn alpn `dns:"-"`
Nodefprotocol bool `dns:"-"`
// other valuews
Value []SvcKeyValue `dns:"svc"` // if priority == 0 this is empty
}
I need to look at the current record, all those `dns:"-"` tagged values are super weird,
if they are not useful to a user they should not be in the struct
|
That was an example of solution, the specification didn't change. In other words, should we keep values in SvcFieldValue struct in the presentation format as string, with conversion functions to go types, or when decoding it should we fill, with values, go-typed spaces in our struct, which are empty when a relevant key=value pair is not found? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hello again,
I've tested this code against my own implementation (written in Python) from rthalley/dnspython#452 (see comment below for a bug I found). The test I did involved running a Go server that serves an SVCB record, and a Python client that queries the record. Hoepfully this can be useful during developement of this PR, so I'll leave the code I wrote below. It currently only tests the alpn
parameter, but it can be easily adapted to test other features as well.
In terms of the exposed Go API, I agree that using only string
for all SvcParamValue
s is not great, as the user will need to know how to manually encode and decode all different values to/from the wire format (which is also different from the presentation format) for most fields. This becomes repetitive as each user will need to basically re-implement the same thing over and over.
I'm not sure using hard-coded fields as suggested in #1067 (comment) would work, as all the parameters are actually optional, so it's not clear to me how a user parsing an SVCB answer would know which parameter is actually set and which isn't (maybe using nullable pointers would work better?).
Given this and the fact that each field type has different presentation and wire formats, I think implementing something like edns.go
would actually be much easier for users to use. Each svc param would implement a common interface, and the user could more easily create and use the different parameter I think (and it would also be easier to add new parameters in the future).
Anyways, thanks for working on this @DesWurstes.
Here is the code for the Go server in my test:
package main
import "fmt"
import "sync"
import "github.com/DesWurstes/dns"
func handleRequest(w dns.ResponseWriter, r *dns.Msg) {
fmt.Println("GOT REQUEST", r)
m := new(dns.Msg)
m.SetReply(r)
svcb := &dns.SVCB{
Hdr: dns.RR_Header{
Name: r.Question[0].Name,
Rrtype: dns.TypeSVCB,
Class: dns.ClassINET,
Ttl: 3600,
},
Priority: 1,
Target: ".",
Value: []dns.SvcKeyValue {
dns.SvcKeyValue{
SvcParamKey: dns.SVC_ALPN,
SvcParamValue: "\x02h3\x02h2",
},
},
}
m.Answer = append(m.Answer, svcb)
w.WriteMsg(m)
}
func main() {
var wg sync.WaitGroup
wg.Add(1)
dns.HandleFunc("svcb.example.", handleRequest)
server := &dns.Server{Addr: ":53", Net: "udp"}
go server.ListenAndServe()
wg.Wait()
}
And here is the Python client:
#!/usr/bin/env python3
import dns.resolver
resolver = dns.resolver.Resolver(configure=False)
resolver.nameservers = ['127.0.0.1']
answer = resolver.query('svcb.example.', 'SVCB')
print(answer.rrset)
msg_helpers.go
Outdated
|
||
func packDataSvc(options []SvcKeyValue, msg []byte, off int) (int, error) { | ||
for _, el := range options { | ||
off, err := packUint16(el.SvcParamKey, msg, off) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know that this is probably going to change anyway, but note that the off
variable here shadows the off
argument variable, so this function always ends up returning the same value that was passed in (effectively the svc fields are not encoded in the output message).
Oh, regarding the dnspython code, note that I accidentally ended up using different code-points there than what is used in this PR, so one or the other needs to be manually changed to make the test work. |
@miekg I'm ditto-ing Lines 217 to 226 in 6737387
Code is only written to and never read (instead of |
svcb.go
Outdated
|
||
// SvcKeyValue defines a key=value pair for SvcFieldValue. | ||
// A SVCB RR can have multiple SvcKeyValues appended to it. | ||
type SvcKeyValue interface { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oh wow. I'm reading section 6 of the draft, that's pretty terrible range of things you can put in this record as key=value thingies.
Note that the EDNS0 stuff has been shown to be suboptimal and isn't the nicest interface to work with, so I rather not have it here again. Having different types implementing SvcKeyValue works for me, so this will be still an interface. However things like Key
and Read
look like overkill. I.e. the interface must be paired down to the absolute minimal
svcb.go
Outdated
// e.Alpn = []string{"h2", "http/1.1"} | ||
// o.Value = append(o.Value, e) | ||
type SVC_ALPN struct { | ||
Code uint16 // Always SVCALPN |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So Code isn't really need here? Maybe that can be the interface Code() uint
? Also the naming of the types should be move Go like and not uppercase with underscores (another mistake in the EDNS0 code). I'm not sure what would make sense here? A subpackage we're these things live? Or prefixing them with Svc
? Note that the final name is not chosen yet? (is this true?) So we might be looking into renaming this in the future
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rather than prefixing every member of each struct I'd prefer to move everything to a SVCB folder/subpackage. What do you think? The specification may be extended by much in the future.
I believe Key()
should stay in the main interface, so that its exposed parts are
type SvcKeyValue interface {
// Key returns the key code of the pair.
Key() uint16
// String returns the string representation of the value.
String() string
}
Just for the record, I was able to implement support for serving HTTPSSVC records in our internal DNS server after pulling these changes (including the latest API tweaks) 🎉 but I'll need to wait for this PR to be merged before starting deployment to production. The new public API exposed to applications is quite nice, so I don't really have anything more to say 👍 |
Hi ghedo, thanks for the feedback you've given, and your dnspython SVCB code, it was essential for me to debug this implementation. :) |
[ Quoting <[email protected]> in "Re: [miekg/dns] Implement SVCB (#10..." ]
@DesWurstes commented on this pull request.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
In svcb.go:
> +
+// SVC_ALPN pair is used to list supported connection protocols.
+// Protocol ids can be found at:
+// https://www.iana.org/assignments/tls-extensiontype-values/
+// tls-extensiontype-values.xhtml#alpn-protocol-ids
+// Basic use pattern for creating an alpn option:
+//
+// o := new(dns.HTTPSSVC)
+// o.Hdr.Name = "."
+// o.Hdr.Rrtype = dns.TypeHTTPSSVC
+// e := new(dns.SVC_ALPN)
+// e.Code = dns.SVCALPN
+// e.Alpn = []string{"h2", "http/1.1"}
+// o.Value = append(o.Value, e)
+type SVC_ALPN struct {
+ Code uint16 // Always SVCALPN
Rather than prefixing every member of each struct I'd prefer to move everything
to a SVCB folder/subpackage. What do you think? The specification may be
extended by much in the future.
I believe Key() should stay in the main interface, so that its exposed parts
are
type SvcKeyValue interface {
// Key returns the key code of the pair.
Key() uint16
// String returns the string representation of the value.
String() string
}
yep, this looks like a sane interface, modulo naming but we can fix that later.
Yes, I'm also inclined to move this to a subpackage, `dnssvcb` or something less
hidious...
|
[ Quoting <[email protected]> in "Re: [miekg/dns] Implement SVCB (#10..." ]
Just for the record, I was able to implement support for serving HTTPSSVC
records in our internal DNS server after pulling these changes (including the
latest API tweaks) 🎉 but I'll need to wait for this PR to be merged before
starting deployment to production.
The new public API exposed to applications is quite nice, so I don't really
have anything more to say 👍
nice cross OSS/DNS work here :)
|
I was dreaming of keeping |
@tmthrgd Thank you for the thorough review, I've addressed them all (or commented). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A few changes.
svcb.go
Outdated
fallthrough | ||
case '\\': | ||
str.WriteByte('\\') | ||
fallthrough |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What I'm saying is replace this with:
case ...:
str.WriteByte('\\')
str.WriteByte(e)
default:
str.WriteByte(e)
svcb.go
Outdated
for _, e := range s.Data { | ||
if (0x1f < e && e < 0x7f) || e == 0x09 { | ||
switch e { | ||
case '"', ';', ' ', '\\', 0x09: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This can't be right for 0x09 (\t), because that would be \
(slash then tab).
svcb.go
Outdated
var str strings.Builder | ||
str.Grow(4 * len(s.Data)) | ||
for _, e := range s.Data { | ||
if (0x1f < e && e < 0x7f) || e == 0x09 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we switch this around so it's like:
if e < ' ' || e > '~' {
str.WriteString(escapeByte(e))
} else {
...
}
svcb.go
Outdated
// areSVCBPairArraysEqual checks if SVCBKeyValue arrays are equal | ||
// after sorting their copies. arrA and arrB have equal lengths, | ||
// otherwise zduplicate.go wouldn't call this function. | ||
func areSVCBPairArraysEqual(arrA []SVCBKeyValue, arrB []SVCBKeyValue) bool { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
They can share the same name: a = append(...)
.
svcb.go
Outdated
func areSVCBPairArraysEqual(arrA []SVCBKeyValue, arrB []SVCBKeyValue) bool { | ||
a := append(make([]SVCBKeyValue, 0, len(arrA)), arrA...) | ||
b := append(make([]SVCBKeyValue, 0, len(arrB)), arrB...) | ||
sort.Slice(a, func(i, j int) bool { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My suggestion here is just to put the existing code onto one line.
Spaces and tabs are treated the same. These are allowed: 1) dnskey="a b"
2) dnskey=a\ b
3) dnskey="a\ b" The current code uses the third form for experimental key=value pairs. It's easy to change it to the first, would you prefer the first?
If: func areSVCBPairArraysEqual(a []SVCBKeyValue, b []SVCBKeyValue) bool {
a := append([]SVCBKeyValue(nil), a...)
b := append([]SVCBKeyValue(nil), b...) Then: ./svcb.go:744:4: no new variables on left side of :=
./svcb.go:745:4: no new variables on left side of := |
Push 2 because can't build fuzzer python Push 3 to try again
Looks like this has gone silent for a while, any update? It seems most review comments have been addressed, but I guess @miekg hasn't had a chance to do his "minimization" pass yet? |
And add the relevant test Force push edit: Make sorting code fit into one line
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A handful of relatively minor changes, and then it should be ready to merge. Thanks for the patience.
} | ||
|
||
func (s *SVCBIPv4Hint) parse(b string) error { | ||
if strings.Contains(b, ":") { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don’t love this check. Is there any harm in letting people use IPv4-in-IPv6 addresses?
svcb.go
Outdated
} | ||
x := make([]net.IP, 0, len(b)/16) | ||
for i := 0; i < len(b); i += 16 { | ||
x = append(x, net.IP(b[i:i+16])) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This doesn’t check for IPv4 addresses, should it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's impossible to check for the address type, this is just a byte array.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A To4() != nil
check was what I was referring to. Not sure if it’s a good idea, but it would seem consistent with other methods on this type.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, if it's okay for you I would prefer not adding conditions that would always evaluate to one branch, To4()
is always nil
for 16-byte IP arrays.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That seems inconsistent with other methods on this type that all have a To4() != nil
check on them. It’s definitely not going to be a hotspot.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, changed it.
} | ||
|
||
func (s *SVCBIPv6Hint) parse(b string) error { | ||
if strings.Contains(b, ".") { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don’t like this check, just check To4() != nil
inside the for-loop.
svcb.go
Outdated
var str strings.Builder | ||
str.Grow(4 * len(s.Data)) | ||
for _, e := range s.Data { | ||
if (0x1f < e && e < 0x7f) || e == 0x09 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I’d still like this to be clearer.
Thank you, this used to be a broken implementation. I've now verified the correctness of its behavior with ghedo's Python tool.
This was to be consistent with #1107, unless something changed in the last few months? |
My memory apparently, months is a life time ago. 😅 If it’s consistent with elsewhere in this library, it’s fine to stay. |
This branch exists to have pull 1067 changes on top of most recent upstream miekg/master branch. This branch took DesWurstes's master branch commit that diverged from commit upstream commit 0ffcea3 and continued to 5cfc4ab. The last commit 5cfc4ab... had title 'More cleanup and fix mandatory not sorting bug'. Reference: miekg#1067 Reference: https://github.com/DesWurstes/dns.git
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm happy with this now, no need to iterate ad infinitum over minor nits. Should be fine to merge. Thanks for your patience.
* Rename ECH, bump draft number * AliasForm new treatment * alpn is no longer mandatory by default * Document the non-empty value requirement * new test cases * more test cases * Continue forbidding v4-map-v6 but not v4-embed-v6 #1067 (comment) and MikeBishop/dns-alt-svc#361 * Update documentation * revert rename ech * Reword AliasMode with key=value pairs
* Implement SVCB * Fix serialization and deserialization of double quotes * More effort (?) 4 months old commit * DEBUG * _ * Presentation format serialization/deserialization * _ Remove generated * Progress on presentation format parse & write * _ * Finish parsing presentation format * Regenerate * Pack unpack * Move to svcb.go Scan_rr.go and types.go should be untouched now * 🐛 Thanks ghedo * Definitions * TypeHTTPSSVC * Generated and isDuplicate * Goodbye lenient functions Now private key=value pairs have to be defined as structs too. They are no longer automatically named as KeyNNNNN * Encode/decode * Experimental svc * Read method * Implement some of the methods, use trick... to report where the error is while reading it. This should be applied to EDNS too. Todo: Find if case can only contain e := new(SVC_ALPN) and rest moved out Also fix two compile errors * Add SVC_LOCAL methods, reorder, remove alpn value, bugs * Errors * Alpn, make it build * Correct testsuite * Fully implement parser Change from keeping a state variable to reading in one iteration until the key=value pair is fully consumed * Simplify and document EDNS should be simplified too * Attempt to fix fuzzer And Alpn bug * A bug and change type values to match @ghedo's implementation * IP bug Also there are two ip duplicating patterns, one with copy, one with append. Maybe change it to be consistent. * Check for strictly increasing keys as required * Don't panic on invalid alpn * Redundant check, don't modify original array * Size calculation * Fix the fuzzer, match the style * 65535 is reserved too, don't delay errors * Check keyNNN, check for aliasform having values * IPvNHint is an array * Fix ipvNHint * Rename everything * Unrecognized keys according to the updated specification * Skip zero-length structs in generators. Fix CI * Doc cleanup * Off by one * Add parse tests * Check if private key doesn't collide with known key, invalid tests * Disallow IPv4 as IPv6. More tests. Related miekg#1107 * Style fixes * More consistency, more tests * 🐛 Deep copy as in the documentation a := make([]net.IP, 1) a[0] = net.ParseIP("1.1.1.1").To4() b := append(make([]net.IP, 0, 1), a...) b[0] = net.ParseIP("3.1.1.1").To4() fmt.Println(a[0][0]) * Make tests readable * Move valid parse tests to different file * 🐛 One of previous commits not fully committed * Test binary single value encoding/decoding and full encode/decode * Add worst-case grows to builders, 🐛 Wrong visible character range, redundant tests * Testing improvements And don't convert to IPv4 twice * Doc update only * Document worst case allocations and ipv6 can be at most of length 39, not 40 * Redundant IP copy, consistent IPv6 behavior, fix deep copy * isDuplicate for SVCB * Optimizations * echoconfig * Svc => SVCB * Fix CI * Regenerate after REBASE (2) Rebased twice on 15th and 20th May * Rename svc, use escapeByte. * Fix parsing whitespaces between quotes, rename ECHOHOConfig * resolve Remove svcbFieldLen Use reverseInt Uppercase SVCB Rename key_value "invalid" => bad Alpn comments > 65535 check Unneeded slices * a little more read => parse IP array meaning Force pushed because forgot to change read in svcb_test.go * HTTPSSVC -> HTTPS * Use new values * mandatory code MikeBishop/dns-alt-svc#205 * Resolve comments Rename svcb-pairs Remove SVCB_PRIVATE ranges Comment on SVCB_KEY65535 ParseError return l.token rename svcbKeyToString and svcbStringToKey privatize SVCBKeyToString, SVCBStringToKey * Refactor 1 Rename sorted, originalPairs Use append instead of copy Use svcb_RESERVED instead of 65535, with it now being private "type SVCBKey uint16" * Refactor 2 svcbKeyToString as method svcbStringToKey updated after key 0 :bug: mandatory has missing key Rename str idx < 0 * Refactor 3 Use l.token as z var key, value string Comment wrap 0: Sentences with '.' keyValue => kv * Refactor 4 * Refactor 5 len() int * Refactor 6 * Refactor 7 * Test remove parsing * Error messages * Rewrite two estimate comments * parse shouldn't modify original array :bug: * Remove two unneeded comments * Address review comments Push 2 because can't build fuzzer python Push 3 to try again * Simplify argument duplication as per tmthrgd's suggestion And add the relevant test Force push edit: Make sorting code fit into one line * Rewrite ECHConfig and address the review * Remove the optional tab * Add To4() Check * More cleanup and fix mandatory not sorting bug
* Rename ECH, bump draft number * AliasForm new treatment * alpn is no longer mandatory by default * Document the non-empty value requirement * new test cases * more test cases * Continue forbidding v4-map-v6 but not v4-embed-v6 miekg#1067 (comment) and MikeBishop/dns-alt-svc#361 * Update documentation * revert rename ech * Reword AliasMode with key=value pairs
Resolves #1064
Seems to work well. Can be tested with @ghedo's python code and his Go code (Now my code uses the same numbers. I've updated his Go code, below, to work with the new edns-like code:)